package com.custom.web.base;

import com.custom.action.condition.Conditions;
import com.custom.action.condition.LambdaConditionWrapper;
import com.custom.action.core.JdbcDao;
import com.custom.action.service.DbServiceImplHelper;
import com.custom.comm.date.DateTimeUtils;
import com.custom.comm.exceptions.CustomCheckException;
import com.custom.comm.page.DbPageRows;
import com.custom.comm.utils.back.BackResult;
import com.custom.comm.utils.back.ResultStatus;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.List;
import java.util.Objects;

/**
 * @author XiaoBai
 * @since 2024/3/3 0003 15:04
 */
public abstract class CommonController<Param extends AbstractQuery<View>, View>
        extends DbServiceImplHelper<View> implements ControllerHandler<Param, View> {

    @Autowired
    protected JdbcDao jdbcDao;

    @Override
    public Class<View> target() {
        return super.targetIndex(1);
    }

    @ApiOperation("根据ID查询单个")
    @GetMapping("/queryById")
    public BackResult<View> queryById(@RequestParam("id") @ApiParam(value = "ID", name = "id", required = true) Integer id) {
        return doTrans(it -> {
            final View view = getByKey(id);
            queryOneAfter(it, view);
            it.success(view);
        });
    }

    @ApiOperation("根据条件查询单个")
    @PostMapping("/queryOne")
    public BackResult<View> queryOne(@RequestBody Param param) {
        return doTrans(it -> {
            queryPageBefore(it, param);
            if (isOpFail(it)) return;
            LambdaConditionWrapper<View> wrapper = Conditions.lambdaQuery(target());
            param.handleQuery(wrapper);
            View view = jdbcDao.selectOne(wrapper);
            if (view != null) {
                queryOneAfter(it, view);
            }
            it.success(view);
        });
    }

    @ApiOperation("分页查询")
    @PostMapping("/queryPage")
    public BackResult<DbPageRows<View>> queryPage(@RequestBody Param param) {
        return doTrans(it -> {
            queryPageBefore(it, param);
            if (isOpFail(it)) return;
            LambdaConditionWrapper<View> wrapper = Conditions.lambdaQuery(target());
            param.handleQuery(wrapper);
            DbPageRows<View> pageRows = jdbcDao.selectPage(wrapper);
            if (!pageRows.getData().isEmpty()) {
                queryPageAfter(it, param, pageRows);
            }
            it.success(pageRows);
        });
    }

    @ApiOperation("添加记录")
    @PostMapping("/add")
    public BackResult<?> add(@RequestBody final View item) {
        return doTrans(it -> {
            addBefore(it, item);
            if (isOpFail(it)) return;
            Integer currTime = currTime();
            if (item instanceof BaseTableInfo) {
                BaseTableInfo<?> tableInfo = (BaseTableInfo<?>) item;
                tableInfo.setCreateTime(currTime);
                tableInfo.setUpdateTime(currTime);
            }
            insert(item);
            addAfter(it, item);
        });
    }

    @ApiOperation("修改记录")
    @PostMapping("/updateById")
    public BackResult<?> updateById(@RequestBody final View item) {
        return doTrans(it -> {
            updateBefore(it, item);
            if (isOpFail(it)) return;
            Integer currTime = currTime();
            if (item instanceof BaseTableInfo) {
                BaseTableInfo<?> tableInfo = (BaseTableInfo<?>) item;
                tableInfo.setUpdateTime(currTime);
            }
            update(item);
            updateAfter(it, item);
        });
    }

    @ApiOperation("根据ID删除记录")
    @GetMapping("/deleteById")
    public BackResult<?> deleteById(@RequestParam("id") @ApiParam(value = "ID", name = "id", required = true) Integer id) {
        return doTrans(it -> {
            final View view = getByKey(id);
            deleteIdBefore(it, view);
            if (isOpFail(it)) return;
            deleteByKey(id);
            deleteIdAfter(it, view);
        });
    }

    @ApiOperation("根据ID批量删除记录")
    @PostMapping("/deleteByIds")
    public BackResult<?> deleteByIds(@RequestBody BatchIdList batch) {
        return doTrans(it -> {
            final List<View> views = getByKeys(batch.getIdList());
            if (!views.isEmpty()) {
                deleteIdsBefore(it, views);
                if (isOpFail(it)) return;
                deleteBatchKeys(batch.getIdList());
                deleteIdsAfter(it, views);
            }
        });
    }



    protected <R> BackResult<R> doTrans(HandleEvent<R> event) {
        return BackResult.execCall(it -> jdbcDao.execTrans(() -> {
            event.handle(it);
        }));
    }

    private static boolean isOpFail(BackResult<?> it) {
        return !Objects.equals(it.getStatus(), ResultStatus.success.getCode());
    }

    public JdbcDao thisJdbcDao() {
        return jdbcDao;
    }

    protected void require(boolean condition, String massage) throws CustomCheckException {
        if (!condition) {
            throw new CustomCheckException(massage);
        }
    }

    protected void require(boolean condition, String massage, Object... params) throws CustomCheckException {
        if (!condition) {
            throw new CustomCheckException(massage, params);
        }
    }

    protected Integer currTime() {
        return DateTimeUtils.getThisTime();
    }


}
